home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dicehelp / MakeIndex.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  11KB  |  451 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7. **      $Id: MakeIndex.c,v 30.5 1994/06/13 18:43:09 dillon Exp dice $
  8. **
  9. **      Generate index file for use by DICEHelp.  Modified from the DME
  10. **      program MakeIndex.
  11. **
  12. **        BUGS: Leaves LF at the end of last entry of some
  13. **        document files (like exec.doc).
  14. **
  15. **              !!! TODO: If clip is within MAGIC_NUMBER of filesize,
  16. **              just return the entire file.
  17. **
  18. **              !!! TODO: OpenDevice/CloseDevice/OpenLibrary/CMD_READ, etc
  19. **              generally don't end up unique.  What to do, to do, to do.
  20. **
  21. **              !!! TODO: Scan for TAG_XXXXX
  22. **
  23. **              !!! TODO: Scan .fd files better
  24. **
  25. **              !!! TODO: On include files, scan backwards to nuke
  26. **              include file header.
  27. **
  28. **              !!! TODO: Bug report on layers line
  29. **
  30. */
  31. #define D(x)    ;
  32.  
  33. /*
  34.  *  MakeIndex output <pattern>
  35.  *
  36.  *  Given one or more autodoc or .H files (e.g. intuition.doc) or include
  37.  *  files (e.g. exec/types.h), this program appends DICEHelp refence file
  38.  *  <refsfile> appropriate lines.
  39.  *
  40.  *  MakeIndex determines the file type from the extension (.h for header
  41.  *  files, otherwise assumed to be a doc file).
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include <MakeIndex_Rev.h>
  47.  
  48. #define unless(x)       if(!(x))
  49.  
  50. char *SetSName(char *, char *);
  51. char *TailPath(char *path);
  52. char *strcpyc(char *d, char *s, char c);
  53. int   globalerrors=0;
  54.  
  55. const char  IdString[] = { VERSTAG };
  56.  
  57. main(xac, xav)
  58. int xac;
  59. char *xav[];
  60. {
  61.     short i;
  62.     FILE *fi;
  63.     FILE *fo;
  64.     int ac;
  65.     char **av;
  66.  
  67.     expand_args(xac, xav, &ac, &av);
  68.  
  69.         // !!! Add ? support
  70.     if (ac == 1) {
  71.     puts("MakeIndex outfile <pattern>");
  72.     exit(1);
  73.     }
  74.     fo = fopen(av[1], "a");
  75.     if (!fo) {
  76.     printf("Error: Unable to open %s for append\n", av[1]);
  77.     globalerrors++;
  78.     exit(1);
  79.     }
  80.     for (i = 2; i < ac; ++i) {
  81.     char *file = av[i];
  82.     short len = strlen(file);
  83.     short doth = 0;
  84.  
  85.     if (len >= 2 && (file[len-1] == 'h' || file[len-1] == 'H') && file[len-2] == '.')
  86.         doth = 1;
  87.  
  88.     if (len >= 2 && (file[len-1] == 'i' || file[len-1] == 'I') && file[len-2] == '.')
  89.         doth = 2;
  90.  
  91.     fi = fopen(file, "r");
  92.     if (fi) {
  93.         if (doth == 1) {
  94.         printf("Scanning .H  file: %s\n", file);
  95.         scanhfile(fi, fo, file);
  96.         } else if (doth == 2) {
  97.         printf("Recording name of .I file: %s\n", file);
  98.         scanifile(fi, fo, file);
  99.         } else {
  100.         printf("Scanning DOC file: %s\n", file);
  101.         scandocfile(fi, fo, file);
  102.         }
  103.         fclose(fi);
  104.     } else {
  105.         printf("Error: Unable to read %s\n", file);
  106.            globalerrors++;
  107.     }
  108.     }
  109.     printf("Operation complete.  %d errors\n",globalerrors);
  110.     return(0);
  111. }
  112.  
  113.  
  114. /*
  115.  *  Find the headers for each function entry and generate a ref entry.
  116.  */
  117.  
  118. scandocfile(fi, fo, filename)
  119. FILE *fi;
  120. FILE *fo;
  121. char *filename;
  122. {
  123.     char buf[256];
  124.     long pos = 0;
  125.     long pendpos = 0;   // Temp for eliminating ^L from resulting file
  126.     long pending =0;    // For calculating # bytes in entry
  127.     short lastLineFF = 0;
  128.     char pendflag=0;            // If flush of line pending
  129. #define    MSIZE    128
  130.     static char pendline[MSIZE];    // Function names copied to here
  131.     char *temp1;
  132.     char *temp2;
  133.     long lin=1;
  134.  
  135.     // Start of new file
  136.     fprintf(fo, "~%s\n", filename);
  137.     fprintf(fo, "%s    %lx    %lx\n",TailPath(filename),0,0);
  138.  
  139.     while (fgets(buf, 256, fi)) {
  140.     short len = strlen(buf) - 1;
  141.     char *ptr = buf + len;
  142.     char *bas = buf;
  143.     char *header, *tail;
  144.  
  145.     buf[len] = 0;
  146.     // Scan backwards to start, or first space or <tab>
  147.     while (ptr != buf && ptr[-1] != ' ' && ptr[-1] != 9)
  148.         --ptr;
  149.     // Skip all ^L
  150.     while (bas < ptr && *bas == 12)
  151.         ++bas;
  152.  
  153.     // Process either:
  154.     //      A>      dice/name                       dice/name
  155.     //
  156.     //      B>      <FF>
  157.     //              anysingleword/withaslash
  158.     //
  159.     //      C>      <FF>anysingleword/withaslash
  160.     //
  161.     //
  162.     if (ptr != bas && *ptr && strncmp(bas, ptr, strlen(ptr)) == 0) {
  163.  
  164.             D(printf("ptr=%s\nbas=%s\nRR:lastLineFF=%d\n",ptr,bas,lastLineFF));
  165.  
  166.             pendpos = pos;      // Snapshot before skipping FF
  167.         if (buf[0] == 12) {
  168.         ++pos;
  169.         buf[0] = 0;
  170.         }
  171.         header = ptr;
  172.         for (ptr = buf + len; ptr != buf && IsAlphaNum(ptr[-1]); --ptr)
  173.             ;
  174.         tail = ptr;
  175.  
  176.             if (pendflag)
  177.                 {
  178.                 D(printf("%s pending\n",pendline));
  179.  
  180.                 // Process all comma separated function names.
  181.                 temp1 = pendline;
  182.                 temp2 = pendline;
  183.                 while( temp2 && *temp1 )
  184.                         {
  185.                         temp2=strchr( temp1, ',' );
  186.                         if( temp2 )
  187.                             *temp2=0;
  188.  
  189.                         fprintf(fo, "%s    %lx    %lx\n",temp1,pending,pendpos-pending);
  190.  
  191.             temp1=temp2+1;    // Skip ,
  192.                     }
  193.                 pendflag=0;
  194.              }
  195.  
  196.             if(!( *tail ))
  197.         {
  198.                 printf("Error: Bad function name! (line %d)\n",lin);
  199.         globalerrors++;
  200.         }
  201.             else{
  202.                 pending  =pos;
  203.                 strncpy( pendline, tail, MSIZE-1 );
  204.                 pendline[MSIZE-1]=0;
  205.                 pendflag =1;
  206.                 }
  207.  
  208.     } else if (ptr == bas && *ptr && strchr(ptr,'/') && (lastLineFF || *ptr==12 )) {
  209.             D(printf("ptr=%s\nbas=%s\nLL:lastLineFF=%d\n",ptr,bas,lastLineFF));
  210.  
  211.             pendpos = pos;      // Snapshot before skipping FF
  212.         if (buf[0] == 12) {
  213.         ++pos;
  214.         buf[0] = 0;
  215.         }
  216.         for (ptr = buf + len; ptr != buf && IsAlphaNum(ptr[-1]); --ptr)
  217.             ;
  218.             tail = ptr;
  219.  
  220.             if (pendflag)
  221.                 {
  222.                 D(printf("LL %s pending\n",pendline));
  223.  
  224.                 // Process all comma separated function names.
  225.                 temp1 = pendline;
  226.                 temp2 = pendline;
  227.                 while( temp2 && *temp1 )
  228.                         {
  229.                         temp2=strchr( temp1, ',' );
  230.                         if( temp2 )
  231.                             *temp2=0;
  232.  
  233.                         fprintf(fo, "%s    %lx    %lx\n",temp1,pending,pendpos-pending);
  234.  
  235.             temp1=temp2+1;    // Skip ,
  236.                     }
  237.                 pendflag=0;
  238.              }
  239.  
  240.             if(!( *tail ))
  241.         {
  242.                 printf("Error: Bad function name! (line %d)\n",lin);
  243.         globalerrors++;
  244.         }
  245.             else{
  246.                 pending  =pos;
  247.                 strncpy( pendline, tail, MSIZE-1 );
  248.                 pendline[MSIZE-1]=0;
  249.                 pendflag =1;
  250.                 }
  251.  
  252.     }
  253.     if (buf[0] == ('l'&0x1F))
  254.         lastLineFF = 1;
  255.     else
  256.         lastLineFF = 0;
  257.     pos = ftell(fi);
  258.     lin++;
  259.     }
  260.  
  261.         if (pendflag)
  262.         {
  263.             D(printf("End: %s pending. %lx:%lx/%lx\n",pendline,pending,pendpos,ftell(fi)));
  264.         
  265.             // Process all comma separated function names.
  266.             temp1 = pendline;
  267.             temp2 = pendline;
  268.             while( temp2 && *temp1 )
  269.                     {
  270.                     temp2=strchr( temp1, ',' );
  271.                     if( temp2 )
  272.                         *temp2=0;
  273.  
  274.                     fprintf(fo, "%s\t%lx\t%lx\n",temp1,pending,ftell(fi)-pending);
  275.  
  276.             temp1=temp2+1;    // Skip ,
  277.                 }
  278.             pendflag=0;
  279.         }
  280. }
  281.  
  282.  
  283. //      Like strcpy, but stops at the given character
  284. char *strcpyc(char *d, char *s, char c)
  285. {
  286.     char *base = d;
  287.  
  288.     while (*d = *s) {
  289.         if (*s == c) {
  290.             *d = 0;
  291.             break;
  292.             }
  293.     ++s;
  294.     ++d;
  295.     }
  296.     return(base);
  297. }
  298.  
  299. /*
  300.  *      Just record the name of .i files encountered.  Don't try to locate
  301.  *      structures (yet).
  302.  *
  303.  */
  304. scanifile(fi, fo, filename)
  305. FILE *fi;
  306. FILE *fo;
  307. char *filename;
  308. {
  309.     // Start of new file
  310.     fprintf(fo, "~%s\n", filename);
  311.     fprintf(fo, "%s    %lx    %lx\n",TailPath(filename),0,0);
  312. }
  313.  
  314.  
  315. /*
  316.  *  Find each structure definition (stupid search, assume struct on left
  317.  *  hand side) then generate dme.refs entry from the end point of the
  318.  *  previous structure to the beginning of the next structure.    That is,
  319.  *  the reference refers to the structure and all fields before and after
  320.  *  it until the next structure (before and after).
  321.  */
  322.  
  323. scanhfile(fi, fo, filename)
  324. FILE *fi;
  325. FILE *fo;
  326. char *filename;
  327. {
  328.     static char buf[256];
  329.     static char sname[128];
  330.     static char lname[128];
  331.     long lin  = 1;
  332.     long lin1;
  333.     long lin2 = 1;
  334.     long pos  = 0;
  335.     long pos1 = 0;
  336.     long pos2 = 0;
  337.     short snameisvalid = 0;
  338.     short newsname = 0;
  339.     short includehack =0;
  340.  
  341.     // Start of new file
  342.     fprintf(fo, "~%s\n", filename);
  343.     fprintf(fo, "%s    %lx    %lx\n",TailPath(filename),0,0);
  344.  
  345.     while (fgets(buf, 256, fi)) {
  346.     char *ptr = buf;
  347.  
  348.         /* Attempt to trim header from first structure.  Assume a #include
  349.         ** is the end of any previous structure definition.
  350.         */
  351.         if ( ptr = strstr(buf,"#include") )
  352.             includehack = 1;                // We're tracking one!
  353.         else
  354.             if (includehack && (ptr=strstr(buf,"#endif")) )
  355.                 pos2 = pos + strlen(buf);
  356.             else
  357.                 includehack = 0;
  358.  
  359.     if ((ptr = strstr(buf, "struct")) || (ptr = strstr(buf, "union"))) {
  360.         if (ptr[0] == 's')
  361.         ++ptr;
  362.         ptr += 5;
  363.  
  364.         ptr = SetSName(lname, ptr);
  365.  
  366.         /*
  367.          *    search for '{'
  368.          */
  369.  
  370.         {
  371.         while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == 12)
  372.             ++ptr;
  373.         if (*ptr == 0) {
  374.             short c = ' ';
  375.             long savpos = ftell(fi);
  376.             while (c == ' ' || c == '\t' || c == '\n' || c == 12)
  377.             c = getc(fi);
  378.             ptr[0] = c;
  379.             ptr[1] = 0;
  380.             fseek(fi, savpos, 0);
  381.         }
  382.         }
  383.  
  384.         if (*ptr == '{' && lname[0]) {
  385.         if (snameisvalid)
  386.             fprintf(fo, "%s    %lx    %lx\n", sname, pos1, pos2-pos1);
  387.         strcpy(sname, lname);
  388.         snameisvalid = 0;
  389.         newsname = 1;
  390.         pos1 = pos2;
  391.         lin1 = lin2;
  392.         }
  393.     }
  394.     pos = ftell(fi);
  395.     ++lin;
  396.  
  397.     if (strstr(buf, "}")) {
  398.         pos2 = pos;
  399.         lin2 = lin;
  400.         snameisvalid = newsname;
  401.     }
  402.     }
  403.     if (snameisvalid)
  404.     fprintf(fo, "%s    %lx    %lx\n", sname, pos1, pos2-pos1);
  405. }
  406.  
  407. /*
  408. **      Extract name from whitespace
  409. */
  410. char *
  411. SetSName(buf, ptr)
  412. char *buf, *ptr;
  413. {
  414.     while (*ptr == ' ' || *ptr == 9)
  415.     ++ptr;
  416.     while (*ptr && *ptr != '\n' && *ptr != ' ' && *ptr != 9 && *ptr != 12)
  417.     *buf++ = *ptr++;
  418.     *buf = 0;
  419.     return(ptr);
  420. }
  421.  
  422.  
  423. /*      0=not alpha
  424. **      1=alpha
  425. */
  426. IsAlphaNum(c)
  427. char c;
  428. {
  429.     if ((c >= 'a' && c <= 'z') ||
  430.     (c >= 'A' && c <= 'Z') ||
  431.     (c >= '0' && c <= '9') ||
  432.     (c == '_') || (c == '-') || (c == ',') || (c == '.') || (c == '(') || (c == ')')
  433.     )
  434.     return(1);
  435.     return(0);
  436. }
  437.  
  438.  
  439. /*
  440. **      Return filename portion of complete path
  441. */
  442. char *TailPath(char *path)
  443. {
  444. char *last;
  445.  
  446.     unless( last=strrchr(path,'/' ) )    // Return last slash...
  447.         unless( last=strrchr(path,':') ) // or if no slash, last :
  448.             return( path );             // or if neither, input string
  449.     return( last+1 );
  450. }
  451.